package com.ruoyi.project.system.function.controller;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.enums.CellExtraTypeEnum;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.framework.config.RuoYiConfig;
import com.ruoyi.framework.web.domain.AjaxResult;
import com.ruoyi.framework.web.exception.DataException;
import com.ruoyi.framework.web.exception.YearDataAlreadyExistsException;
import com.ruoyi.project.system.function.listener.FunctionListener;
import com.ruoyi.project.system.function.service.FunctionService;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URL;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
*
*
* @Author: 郑吉志
*
* @Create: 23.2.22
**/
@Controller
@RequestMapping("/system/function")
public class FunctionController {
    private final String prefix = "system/function";
    @Autowired
    FunctionService functionService;

    @RequiresPermissions("system:function:view")
    @GetMapping()
    //ModelMap 是一个Spring Web框架中的类，用于在Controller方法中传递数据到视图中。它实现了 Map 接口，底层使用 HashMap 存储键值对。
    //在控制器方法中，通过使用 ModelMap 对象的 put 方法来添加数据，数据会被存储在 ModelMap 对象中，然后在视图模板中可以通过 ${key}
    // 表达式来获取这些数据。在方法执行完成后，Spring框架会将 ModelMap 对象中保存的数据传递给视图解析器，从而渲染出正确的HTML页面。
    public String function(ModelMap mmap){
        Date date=new Date();
        //SimpleDateFormat 对象，用于将日期格式化为年份的字符串。
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy");
        //使用了 yyyy 作为日期格式化模板，代表将日期格式化为 4 位数的年份。
        // 例如，如果当前时间是 2022 年 7 月 21 日 10 点 30 分，则执行 sdf.format(date) 返回的字符串就是 "2022"。
        //就是将才获取的年份与月份日期装换成年份的字符串
        mmap.put("year",sdf.format(date));
        return prefix+"/function";
    }

    @PostMapping ("/import")
    @ResponseBody
    //@RequestParam(“file”)表示从请求参数中获取名为file的文件数据，并将其映射到方法参数中的MultipartFile类型对象file中。
    //MultipartFile是Spring MVC框架提供的一个接口，用于处理HTTP POST请求中的文件上传
    public AjaxResult familyRead(@RequestParam("file") MultipartFile file) throws IOException {
        //EasyExcel.read是EasyExcel读取Excel文件的入口方法。
        //通过file.getInputStream()方法获取上传文件的输入流，从而实现对上传文件的读取和处理。
        //new FunctionListener(functionService) 创建了一个FunctionListener实例，它会将Excel中每一行数据传递给functionService中的方法进行处理；
        //extraRead(CellExtraTypeEnum.MERGE) 表示在读取Excel时处理单元格的合并情况；
        //sheet() 表示读取Excel中的所有工作表；
        //doRead() 执行读取操作Z
        //总之，读取上传的Excel文件，并且通过FunctionListener传递Excel中的每一行数据到functionService中的方法进行处理，
        //同时也支持对Excel中的单元格合并情况进行处理。
        EasyExcel.read(file.getInputStream(),new FunctionListener(functionService)).extraRead(CellExtraTypeEnum.MERGE).sheet().doRead();;
        return AjaxResult.success();
    }


    @GetMapping("/export")
    @ResponseBody
    public void mt(HttpServletResponse response, HttpServletRequest request) throws Exception {
        //使用UUID.fastUUID()方法获取一个唯一标识符,将其转换成字符串类型，再使用substring()方法提取前9个字符作为文件名的一部分;
        //这段Java代码使用URLEncoder对字符串进行UTF-8编码，以便在文件系统中能正确地显示中文字符,有利于浏览器、服务器和其他网络设备正确识别并处理这些字符。
        //eg:4c41dfdc-导入表模板
        String filename= UUID.fastUUID().toString().substring(0,9)+URLEncoder.encode("导入表模板", "UTF-8");
        //设置响应头信息，以便浏览器能够正确地识别和处理文件下载操作
        //  Content-disposition是一个HTTP响应头字段，用于指示对客户端该如何处理响应体信息。这里设置为"attachment"，表示响应体是以附件形式下载的
        //上面生成的文件名加上后缀.xlsx
        response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + filename + ".xlsx");
        //getCanonicalPath()方法返回的是当前工作目录的绝对路径（不包括"/.“和”/…"，可以更好地反映真实的目录结构）
        //linux路径
//       String filePath="/home/ruoyi/uploadPath/import.xlsx";
        //win路径
        File file = new File("");
        String path = file.getCanonicalPath();
        String filePath=path+"/src/main/resources/static/Template1/import.xlsx";
        response.setCharacterEncoding("utf-8");
        response.setContentType("multipart/form-data");
        response.setHeader("Content-Disposition",
                "attachment;filename*=utf-8''" + filename + ".xlsx");
        FileUtils.writeBytes(filePath, response.getOutputStream());
    }


    @PostMapping("/add")
    @ResponseBody
    //为什么使用@RequestBody
    //建议使用@RequestBody注解，因为它可以让Spring Boot自动将JSON请求中的参数映射到Java对象上，并自动完成类型转换操作，减少程序员的工作量。
    public AjaxResult add(@RequestBody String year){
        year=year.substring(0,year.length()-1);
    //获取所选年份在一级收入表里的一个list<Integer>集合
        List<Integer> selectYear = functionService.selectYear(Integer.parseInt(year));
        //将数据库中农户户主表未销户的每户户编号存到一个集合里面
        List<String> fidList=functionService.selectNumFarmer();
        //将上一年一级收入表中未封停数据取出
        Integer state=functionService.selectStateByYear(Integer.parseInt(year)-1);
        //表示去年数据未封停
        if (state!=null&&state==0)
            throw new DataException("请先封停去年数据。");
        if (selectYear.size()==fidList.size())//现有户的数量与年份表单记载的户的数量对比,
            throw new YearDataAlreadyExistsException("该年份信息已存在。");
        Integer newYear= Integer.valueOf(year);
        //从2024年开始进行判断，因为如果没有数据的话需要新建2023的，但是没有2022的，如果不加这个判断那么2023年的数据将会建立不了
        if(newYear>2023&&functionService.selectStateByYear(newYear-1)==null)
            throw new YearDataAlreadyExistsException("隔年不能新建年份表单。");
        //在户主表里面查找为销户即现有的户的户编号放进集合内
        List<String> list = functionService.selectFidList();
        for (String str:list)
            //将年份与户编号同时传入以供循环
            functionService.add(Integer.parseInt(year), str);



        return AjaxResult.success();
    }
    @GetMapping("/seal")
    @ResponseBody
    public AjaxResult seal(String flag, String year){
        //通过该年份查询所有该年份的一个集合
        List<Integer> selectYear = functionService.selectYear(Integer.parseInt(year));

        if (selectYear==null)
            throw new YearDataAlreadyExistsException(year+"年信息不存在。");

        functionService.seal(flag,year);
        return AjaxResult.success();
    }
}